#pragma once
#include "tracker.h"
class CArcAnnulus :
  public CTracker
{
  enum HandleNumber
  {
    kInnerStart = 0,
    kOuterStart = 1,
    kInnerEnd   = 2,
    kOuterEnd   = 3,

    kHandleNumberButt
  };

  // Hit-Test codes
  enum TrackerHit
  {
    kHitNothing     = -1,
    kHitInnerBorder = 0,
    kHitOuterBorder = 1,
    kHitStartSpoke  = 2,
    kHitEndSpoke    = 3,
    kHitInnerStart  = 4,
    kHitOuterStart  = 5,
    kHitInnerEnd    = 6,
    kHitOuterEnd    = 7,
    kHitMiddle      = 8,

    kHitButt
  };

  // Keystroke-Test codes
  enum KeyStroke
  {
    kStrokeNothing           = -1,
    kStrokeLineUp            = 0,
    kStrokeLineDown          = 1,
    kStrokeLineLeft          = 2,
    kStrokeLineRight         = 3,
    kStrokePageUp            = 4,
    kStrokePageDown          = 5,
    kStrokePageLeft          = 6,
    kStrokePageRight         = 7,
    kStrokeLineInnerInflate  = 8,
    kStrokeLineInnerDeflate  = 9,
    kStrokeLineOuterInflate  = 10,
    kStrokeLineOuterDeflate  = 11,
    kStrokePageInnerInflate  = 12,
    kStrokePageInnerDeflate  = 13,
    kStrokePageOuterInflate  = 14,
    kStrokePageOuterDeflate  = 15,

    kStrokeButt
  };

public:
  struct ArcAnnulus {
    double x;
    double y;
    double inner;
    double outer;
    double start;
    double end;
  };

public:
  CArcAnnulus(double x, double y, double inner, double outer, double start,
    double end);
  ~CArcAnnulus(void);

public:
  void LeftButtonDown_slot(CWnd* sender, const MouseArgument& arg);
  void LeftButtonUp_slot(CWnd* sender, const MouseArgument& arg);
  void MouseMove_slot(CWnd* sender, const MouseArgument& arg);
  bool CursorSet_slot(CWnd* sender, const MouseArgument& arg);

public:
  void Draw(Hlong halcon_wnd_handle);
  void AdjustHandles(void);

public:
  ArcAnnulus arc_annulus(void) const { return arc_annulus_; }
  void set_arc_annulus(const ArcAnnulus &arc_annulus)
  {
    arc_annulus_ = arc_annulus;
    AdjustHandles();
  }

private:
  bool CursorOn(const geometry::Point2D &point) const;
  void HitTest(const geometry::Point2D& point);
  void TrackTo(const geometry::Point2D& point);

  void TrackInnerBorder(const geometry::Point2D &vec)
  { 
    arc_annulus_.inner = sqrt(vec.x()*vec.x() + vec.y()*vec.y());
  }

  void TrackOuterBorder(const geometry::Point2D &vec)
  { 
    arc_annulus_.outer = sqrt(vec.x()*vec.x() + vec.y()*vec.y());
  }

  void TrackStartSpoke(const geometry::Point2D &vec)
  {
    double angle = VectorAngle(vec.x(), vec.y());
    double sweep = AngleSweep(angle, arc_annulus_.end);
    double delta = fabs(sweep-sweep_);

    if(delta<90) {
      arc_annulus_.start = angle;
    }
  }

  void TrackEndSpoke(const geometry::Point2D &vec)
  {
    double angle = VectorAngle(vec.x(), vec.y());
    double sweep = AngleSweep(arc_annulus_.start, angle);
    double delta = fabs(sweep-sweep_);

    if(delta<90) {
      arc_annulus_.end = angle;
    }
  }

private:
  ArcAnnulus        arc_annulus_;
  double            sweep_;
  geometry::Rect2D  handles_[4];
  geometry::Point2D vertexes_[4];
  TrackerHit        hit_code_;
};

